package edu.ynu.se.xiecheng.achitectureclass.common.service;

import edu.ynu.se.xiecheng.achitectureclass.common.dao.DeviceDataDao;
import edu.ynu.se.xiecheng.achitectureclass.common.utils.TokenUtil1;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 服务层类，用于处理设备数据的业务逻辑
 *
 * **设计模式：**
 * - **服务模式 (Service Layer Pattern)**：
 *   将业务逻辑从控制器中抽离出来，保持代码的职责单一。
 *
 * **设计原则：**
 * - **单一职责原则 (SRP)**：
 *   该类专注于设备数据的业务逻辑处理。
 * - **依赖注入原则 (DIP)**：
 *   通过构造函数和类成员变量注入依赖。
 */
@Service
public class DeviceDataService {

    // 依赖的 DAO 对象，用于与数据库交互
    private final DeviceDataDao deviceDataDao = new DeviceDataDao();

    /**
     * 从 FBox API 获取设备数据
     *
     * **设计模式：**
     * - **模板方法模式 (Template Method Pattern)**：
     *   使用 `RestTemplate` 调用外部 API。
     *
     * @param token 访问令牌
     * @param boxNo 设备盒号
     * @param ids   设备 ID 列表
     * @return 从 API 返回的设备数据列表
     */
    public List<Map<String, Object>> fetchDeviceData(String token, String boxNo, List<String> ids) {
        String url = "https://fbox360.com/api/v2/dmon/value/get?boxNo=" + boxNo;

        // 设置请求头
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.setBearerAuth(token);

        // 构造请求体
        Map<String, Object> requestBody = new HashMap<>();
        requestBody.put("ids", ids);

        try {
            RestTemplate restTemplate = new RestTemplate();
            HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<>(requestBody, headers);

            // 调用 API
            ResponseEntity<List> response = restTemplate.exchange(url, HttpMethod.POST, requestEntity, List.class);

            // 验证响应并返回数据
            if (response.getStatusCode() == HttpStatus.OK && response.getBody() != null) {
                return response.getBody();
            } else {
                throw new RuntimeException("Failed to fetch device data. Status code: " + response.getStatusCode());
            }
        } catch (Exception e) {
            throw new RuntimeException("Failed to fetch device data.", e);
        }
    }

    /**
     * 获取设备数据并保存到数据库，同时返回数据的 `value` 字段
     *
     * **事务管理：**
     * - 数据获取和保存应作为一个逻辑单元。
     *
     * @param boxNo 设备盒号
     * @param ids   设备 ID 列表
     * @return 数据的 `value` 字段列表
     */
    public List<Double> fetchAndSaveDeviceData(String boxNo, List<String> ids) {
        // 使用工具类获取访问令牌
        String token = TokenUtil1.fetchToken();

        // 从 API 获取设备数据
        List<Map<String, Object>> deviceData = fetchDeviceData(token, boxNo, ids);

        // 保存数据到数据库
        deviceDataDao.saveDataToDatabase(deviceData);

        // 提取并返回 `value` 字段
        List<Double> values = new ArrayList<>();
        for (Map<String, Object> data : deviceData) {
            if (data.containsKey("value") && data.get("value") instanceof Number) {
                values.add(((Number) data.get("value")).doubleValue());
            }
        }

        return values;
    }
}
